package com.lucenten.collect.gnss.handler.impl;

import cn.quevo.common.lang.DateFormatUtils;
import cn.quevo.common.lang.NumberUtils;
import com.lucenten.collect.exec.ShellRun;
import com.lucenten.collect.gnss.entity.GnssFile;
import com.lucenten.collect.gnss.enums.FileSuffix;
import com.lucenten.collect.gnss.enums.GnssFormat;
import com.lucenten.collect.gnss.enums.GnssType;
import com.lucenten.collect.gnss.handler.AbstractGnssHandler;
import com.lucenten.collect.gnss.handler.GnssHandler;
import com.lucenten.collect.gnss.handler.tools.GnssContext;
import com.lucenten.collect.gnss.handler.tools.IgsUnzip;
import com.lucenten.collect.gnss.service.ObsErvationService;
import com.lucenten.collect.gnss.service.SatelliteStationService;
import com.lucenten.collect.utils.FileUtils;
import com.lucenten.mq.SendJmsInfo;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;

/**
 * 第一步：解压->重命名->备份->o文件的TEQC
 */
@Slf4j
public class UnZipGnssHandler extends AbstractGnssHandler implements GnssHandler {
    public UnZipGnssHandler(SatelliteStationService satelliteStationService, ObsErvationService obsErvationService) {
        super(satelliteStationService, obsErvationService);
    }

    @Override
    protected boolean doProcess(GnssFile gnssFile) {
        gnssFile.setDirFiles(new ArrayList<>());
        return unzip(gnssFile.getSourceFile(), gnssFile);
    }

    private boolean unzip(String file, GnssFile gnssFile) {
        Path source = Paths.get(file);
        gnssFile.setFile(source);
        String fileName = source.getFileName().normalize().toString().toLowerCase();
        gnssFile.setFileName(fileName);
        gnssFile.setRealType(GnssFile.REAL_TYPE_TIME);
        if (fileName.endsWith("t02")) {
            analysisT02(gnssFile);
            return true;
        }
        if (fileName.endsWith("d.z")) {
            analysisDZ(gnssFile);
            return true;
        }
        gnssFile.setGnssType(GnssType.GNSS);
        String[] names = fileName.toString().split("_");

        /**
         * 如果文件不是ZIP文档或者文档不是次站点的，直接当错误文档处理
         */
        if (!this.analysisNames(names, gnssFile)) {
            return true;
        }
        Path targetPath = Paths.get(super.getDataFormatPath(GnssFormat.RINEX, gnssFile));
        try (FileSystem fs = FileSystems.newFileSystem(source, null);) {
            if (Files.notExists(targetPath)) {
                Files.createDirectories(targetPath);
            }
            Files.walkFileTree(fs.getPath("/"), new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path zipFile, BasicFileAttributes attrs) throws IOException {
                    copy(zipFile, gnssFile);
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                    return FileVisitResult.CONTINUE;
                }
            });
//            SendJmsInfo.sendGnssMq(4, gnssFile.getFileName(), 0);
        } catch (IOException e) {
            log.error("文件解压失败",e);
            SendJmsInfo.sendGnssMq(4, gnssFile.getFileName(), 1);
            return false;
        }
        return true;
    }

    private void copy(Path zipFile, GnssFile gnssFile) {
//        Path source = Paths.get(gnssFile.getSourceFile().getParent().normalize().toString(),zipFile.getFileName().normalize().toString());
        final String fileName = getRealName(zipFile.getFileName().normalize().toString().toLowerCase(), gnssFile);
        FileSuffix suffix = FileUtils.getFileSuffix(fileName);
        // 如果是.dat文件
        if (suffix.equals(FileSuffix.DAT)) {
            gnssFile.getDirFiles().add(zipFile.getFileName().normalize().toString().toLowerCase());
            // 保留原始文件名称
            FileUtils.copy(zipFile, Paths.get(super.getTempPath("d", gnssFile), zipFile.getFileName().normalize().toString().toLowerCase()));
            return;
        }

        gnssFile.getDirFiles().add(fileName);
        FileUtils.createDirs(super.getUnZipPath(gnssFile, fileName).getParent());
        // 验证是否.O文件，如果是.O文件需要单独处理
        if (!suffix.equals(FileSuffix.O)) {
            FileUtils.copy(zipFile, super.getUnZipPath(gnssFile, fileName));
            return;
        }
        // 复制O文件
        FileUtils.copy(zipFile, Paths.get(super.getTempPath("o", gnssFile), fileName));
    }

    private boolean analysisNames(String[] names, GnssFile gnssFile) {
        if (!gnssFile.getFileName().toLowerCase().endsWith(".zip")) {
            return false;
        }

        // TODO 目前只有 rnx.zip 文件格式,其他格式需要其他的解析方式
        gnssFile.setStationId(names[3]);
        this.initDateTime(LocalDateTime.ofInstant(DateFormatUtils.parse(names[4], GnssFile.DATE_FORMAT).toInstant(), ZoneId.systemDefault()), gnssFile);
        return true;
    }

    /**
     * 初始化文件日期
     *
     * @param localDateTime
     * @param gnssFile
     */
    private void initDateTime(LocalDateTime localDateTime, GnssFile gnssFile) {
        gnssFile.setDate(localDateTime);
        gnssFile.setYear(localDateTime.getYear());
        gnssFile.setMonth(localDateTime.getMonthValue());
        gnssFile.setDay(localDateTime.getDayOfMonth());
        gnssFile.setDayOfYear(localDateTime.getDayOfYear());
        gnssFile.setHoure(localDateTime.getHour());
        gnssFile.setMinute(localDateTime.getMinute());
        gnssFile.setDateStr(localDateTime.format(DateTimeFormatter.ofPattern(GnssFile.DATE_FORMAT)));
    }

    /**
     * 获取实际存储文件名称
     *
     * @param fileName
     * @param gnssFile
     * @return
     */
    private String getRealName(String fileName, GnssFile gnssFile) {
        String stationName = super.getSetationName(fileName);
        stationName = super.getOrReplaceStation(stationName, gnssFile);
        return stationName + NumberUtils.format(gnssFile.getDayOfYear(), "000") + GnssContext.TIME_CODE[gnssFile.getHoure()] + NumberUtils.format(gnssFile.getMinute(), "00") + (fileName.lastIndexOf(".") != -1 ? fileName.substring(fileName.lastIndexOf(".")) : "");
    }

    /**
     * T02文件解析
     *
     * @param gnssFile
     * @return
     */
    private boolean analysisT02(GnssFile gnssFile) {
        gnssFile.setGnssType(GnssType.CMONC);
        gnssFile.setStationId("lutai");
        try {
            String fileName = this.getFileNameByDate(gnssFile);
            gnssFile.getDirFiles().add(fileName+".dat");
            Path dPath = Paths.get(super.getTempPath("d", gnssFile), fileName);
            FileUtils.createDirs(dPath);
            ShellRun.execOutPut(super.getRunpkr00Run(gnssFile.getIndex()) + " -d " + gnssFile.getFile().normalize().toString() + " " + dPath.normalize().toString());
//            SendJmsInfo.sendGnssMq(2, gnssFile.getFileName(), 0);
        } catch (IOException e) {
            log.error(gnssFile.getFile().normalize().toString() + "T02 解析失败", e);
            SendJmsInfo.sendGnssMq(2, gnssFile.getFileName(), 1);
        }
        return false;
    }

    private boolean analysisDZ(GnssFile gnssFile) {
        gnssFile.setGnssType(GnssType.IGS);
        gnssFile.setStationId("igs");
        try {
            String fileName = this.getFileNameByDate(gnssFile)+"."+gnssFile.getYear().toString().substring(2);
            // O文件路径
            Path tmpPath = Paths.get(super.getTempPath("o", gnssFile));
            Path nPath = super.getUnZipPath(gnssFile, fileName+"n");
            Path gPath = super.getUnZipPath(gnssFile, fileName+"g");
            Path mPath = super.getUnZipPath(gnssFile, fileName+"m");
            IgsUnzip.analysisDZ(gnssFile, fileName,tmpPath,nPath,gPath,mPath,super.getCrx2rnxRun(gnssFile.getIndex()));
//            SendJmsInfo.sendGnssMq(3, gnssFile.getFileName(), 0);
        }catch (IOException e) {
            log.error(gnssFile.getFile().normalize().toString() + "DZ 解析失败", e);
            SendJmsInfo.sendGnssMq(3, gnssFile.getFileName(), 1);
        }
        return false;
    }

    /**
     * 获取实际文件名称
     *
     * @param gnssFile
     * @return
     * @throws IOException
     */
    private String getFileNameByDate(GnssFile gnssFile) throws IOException {
        BasicFileAttributes attributes = Files.readAttributes(gnssFile.getFile(), BasicFileAttributes.class);
        LocalDateTime localDateTime = LocalDateTime.ofInstant(attributes.lastModifiedTime().toInstant(), ZoneId.of("UTC"));
        String fileName = gnssFile.getFileName().toLowerCase().substring(0, gnssFile.getFileName().indexOf("."));
        Integer year = localDateTime.getYear();
        Integer dayOfYear = NumberUtils.toInt(fileName.substring(4, 7));
        Integer hour = GnssContext.convertHour(fileName.substring(7, 8));
        localDateTime = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
        localDateTime = localDateTime.withYear(year).withDayOfYear(dayOfYear).withHour(hour).withMinute(0).withSecond(0).withNano(0);
        this.initDateTime(localDateTime, gnssFile);
        return this.getRealName(fileName, gnssFile);
    }
}
